<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>语音对话测试</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .header { margin-bottom: 20px; }
        .section { margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
        .recording { background: #ffe6e6; border-color: #ff9999; }
        .result { background: #f5f5f5; padding: 10px; border-radius: 3px; margin-top: 10px; white-space: pre-wrap; }
        button { padding: 12px 20px; margin: 5px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; }
        .record-btn { background: #dc3545; color: white; }
        .record-btn:hover { background: #c82333; }
        .record-btn.recording { background: #ff4757; animation: pulse 1s infinite; }
        .play-btn { background: #28a745; color: white; }
        .test-btn { background: #007bff; color: white; }
        select { padding: 8px; margin: 5px; }
        .status { padding: 10px; margin: 10px 0; border-radius: 5px; }
        .success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
        .info { background: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb; }
        @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } }
        .audio-controls { margin: 10px 0; }
        .log { background: #f8f9fa; border: 1px solid #dee2e6; padding: 10px; margin: 10px 0; border-radius: 5px; max-height: 200px; overflow-y: auto; font-family: monospace; font-size: 12px; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🎤️ AI角色扮演语音对话测试</h1>
        </div>
        
        <!-- 系统状态 -->
        <div class="section">
            <h2>📊 系统状态</h2>
            <button class="test-btn" onclick="checkCapabilities()">检查系统能力</button>
            <div id="capabilities" class="result"></div>
        </div>

        <!-- 完整语音对话 -->
        <div class="section" id="voiceChatSection">
            <h2>🗣️ 完整语音对话</h2>
            <p>说话 → AI识别 → AI回复 → 语音播放</p>
            
            <div>
                <label>选择AI角色：</label>
                <select id="personaSelect">
                    <option value="SG">苏格拉底 (哲学家)</option>
                    <option value="SW">孙悟空 (齐天大圣)</option>
                    <option value="DF">达芬奇 (艺术家)</option>
                </select>
                
                <label>选择音色：</label>
                <select id="voiceSelect">
                    <option value="xiaochen">小陈 (男声)</option>
                    <option value="jam">Jam (活泼男声)</option>
                    <option value="tongtong">彤彤 (女声)</option>
                    <option value="chuichui">锤锤 (女声)</option>
                </select>
            </div>
            
            <div class="audio-controls">
                <button id="voiceRecordBtn" class="record-btn" onclick="toggleVoiceRecording()">
                    🎤 点击录音
                </button>
                <span id="voiceStatus" class="status"></span>
            </div>
            
            <div id="voiceResult" class="result"></div>
            <audio id="voiceResponsePlayer" controls style="width: 100%; margin-top: 10px; display: none;"></audio>
        </div>

        <!-- 单独功能测试 -->
        <div class="section">
            <h2>🔧 单独功能测试</h2>
            
            <!-- 语音识别测试 -->
            <div style="margin-bottom: 20px;">
                <h3>语音识别 (ASR)</h3>
                <button id="asrRecordBtn" class="record-btn" onclick="toggleASRRecording()">
                    🎤 录音识别
                </button>
                <div id="asrResult" class="result"></div>
            </div>
            
            <!-- 语音合成测试 -->
            <div>
                <h3>语音合成 (TTS)</h3>
                <input type="text" id="ttsText" placeholder="输入要合成的文本..." value="你好，我是AI助手。" style="width: 300px; padding: 8px;">
                <button class="test-btn" onclick="testTTS()">🔊 合成语音</button>
                <audio id="ttsPlayer" controls style="width: 100%; margin-top: 10px; display: none;"></audio>
            </div>
        </div>

        <!-- 日志 -->
        <div class="section">
            <h2>📝 操作日志</h2>
            <button onclick="clearLog()" style="background: #6c757d; color: white; padding: 5px 10px;">清空日志</button>
            <div id="logArea" class="log"></div>
        </div>
    </div>

    <script>
        let isVoiceRecording = false;
        let isASRRecording = false;
        let voiceMediaRecorder = null;
        let asrMediaRecorder = null;
        let currentSessionId = null;

        function log(message) {
            const timestamp = new Date().toLocaleTimeString();
            const logArea = document.getElementById('logArea');
            logArea.innerHTML += `[${timestamp}] ${message}\n`;
            logArea.scrollTop = logArea.scrollHeight;
        }

        function clearLog() {
            document.getElementById('logArea').innerHTML = '';
        }

        function setStatus(elementId, message, type = 'info') {
            const element = document.getElementById(elementId);
            element.textContent = message;
            element.className = `status ${type}`;
        }

        // 页面加载时初始化
        window.onload = function() {
            // 直接初始化页面，无需认证
            initializePage();
        };

        function initializePage() {
            // 从URL参数获取初始角色
            const urlParams = new URLSearchParams(window.location.search);
            const initials = urlParams.get('initials');
            if (initials) {
                const personaSelect = document.getElementById('personaSelect');
                if (personaSelect) {
                    personaSelect.value = initials;
                    log(`从URL参数设置角色: ${initials}`);
                }
            }
            
            log('页面初始化完成');
        }

        // 检查系统能力
        async function checkCapabilities() {
            try {
                log('检查系统能力...');
                const response = await fetch('/api/voice/capabilities');
                const data = await response.json();
                
                let result = '系统能力状态:\n';
                result += `ASR状态: ${data.asrHealthy ? '✅ 正常' : '❌ 异常'}\n`;
                result += `TTS状态: ${data.ttsHealthy ? '✅ 正常' : '❌ 异常'}\n`;
                result += `支持的语言: ${data.supportedLanguages.join(', ')}\n`;
                result += `支持的音色: ${data.supportedVoices.join(', ')}\n`;
                result += `支持的音频格式: ${data.supportedAudioFormats.join(', ')}`;
                
                document.getElementById('capabilities').textContent = result;
                log('系统能力检查完成');
            } catch (error) {
                log(`系统能力检查失败: ${error.message}`);
                document.getElementById('capabilities').textContent = '检查失败: ' + error.message;
            }
        }

        // 完整语音对话
        async function toggleVoiceRecording() {
            const btn = document.getElementById('voiceRecordBtn');
            
            if (!isVoiceRecording) {
                try {
                    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                    voiceMediaRecorder = new MediaRecorder(stream);
                    const audioChunks = [];
                    
                    voiceMediaRecorder.ondataavailable = (event) => {
                        audioChunks.push(event.data);
                    };
                    
                    voiceMediaRecorder.onstop = async () => {
                        const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
                        await processVoiceChat(audioBlob);
                        stream.getTracks().forEach(track => track.stop());
                    };
                    
                    voiceMediaRecorder.start();
                    isVoiceRecording = true;
                    btn.textContent = '🛑 停止录音';
                    btn.classList.add('recording');
                    setStatus('voiceStatus', '正在录音，请说话...', 'info');
                    log('开始语音对话录音');
                    
                } catch (error) {
                    log(`录音失败: ${error.message}`);
                    setStatus('voiceStatus', '录音失败: ' + error.message, 'error');
                }
            } else {
                voiceMediaRecorder.stop();
                isVoiceRecording = false;
                btn.textContent = '🎤 点击录音';
                btn.classList.remove('recording');
                setStatus('voiceStatus', '录音结束，处理中...', 'info');
                log('停止录音，开始处理');
            }
        }

        async function processVoiceChat(audioBlob) {
            try {
                const persona = document.getElementById('personaSelect').value;
                const voice = document.getElementById('voiceSelect').value;
                
                setStatus('voiceStatus', '处理语音对话中...', 'info');
                log(`开始语音对话处理 - 角色: ${persona}, 音色: ${voice}`);
                
                const formData = new FormData();
                formData.append('audio', audioBlob, 'voice-input.wav');
                formData.append('personaId', persona);
                formData.append('voice', voice);
                formData.append('language', 'zh-CN');
                if (currentSessionId) {
                    formData.append('sessionId', currentSessionId);
                }
                
                const response = await fetch('/api/voice/chat', {
                    method: 'POST',
                    body: formData
                });
                
                if (response.ok) {
                    // 从响应头获取处理信息
                    const sessionId = response.headers.get('X-Session-Id');
                    // 解码Base64编码的中文文本
                    const recognizedTextBase64 = response.headers.get('X-Recognized-Text-Base64');
                    const responseTextBase64 = response.headers.get('X-Response-Text-Base64');
                    
                    let recognizedText = '未知';
                    let responseText = '未知';
                    
                    if (recognizedTextBase64) {
                        try {
                            const bytes = Uint8Array.from(atob(recognizedTextBase64), c => c.charCodeAt(0));
                            recognizedText = new TextDecoder('utf-8').decode(bytes);
                        } catch (e) {
                            console.warn('识别文本解码失败:', e);
                        }
                    }
                    
                    if (responseTextBase64) {
                        try {
                            const bytes = Uint8Array.from(atob(responseTextBase64), c => c.charCodeAt(0));
                            responseText = new TextDecoder('utf-8').decode(bytes);
                        } catch (e) {
                            console.warn('响应文本解码失败:', e);
                        }
                    }
                    
                    const processingTime = response.headers.get('X-Processing-Time');
                    
                    currentSessionId = sessionId;
                    
                    // 显示处理结果
                    let result = `会话ID: ${sessionId}\n`;
                    result += `识别的文本: ${recognizedText}\n`;
                    result += `AI回复: ${responseText}\n`;
                    result += `处理时间: ${processingTime}ms`;
                    
                    document.getElementById('voiceResult').textContent = result;
                    
                    // 播放音频响应
                    const audioBlob = await response.blob();
                    const audioUrl = URL.createObjectURL(audioBlob);
                    const player = document.getElementById('voiceResponsePlayer');
                    player.src = audioUrl;
                    player.style.display = 'block';
                    player.play();
                    
                    setStatus('voiceStatus', '语音对话完成！', 'success');
                    log(`语音对话成功 - 耗时: ${processingTime}ms`);
                } else {
                    const errorMsg = response.headers.get('X-Error') || '语音对话失败';
                    setStatus('voiceStatus', errorMsg, 'error');
                    log(`语音对话失败: ${errorMsg}`);
                }
                
            } catch (error) {
                setStatus('voiceStatus', '处理失败: ' + error.message, 'error');
                log(`语音对话处理失败: ${error.message}`);
            }
        }

        // 单独ASR测试
        async function toggleASRRecording() {
            const btn = document.getElementById('asrRecordBtn');
            
            if (!isASRRecording) {
                try {
                    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                    asrMediaRecorder = new MediaRecorder(stream);
                    const audioChunks = [];
                    
                    asrMediaRecorder.ondataavailable = (event) => {
                        audioChunks.push(event.data);
                    };
                    
                    asrMediaRecorder.onstop = async () => {
                        const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
                        await testASR(audioBlob);
                        stream.getTracks().forEach(track => track.stop());
                    };
                    
                    asrMediaRecorder.start();
                    isASRRecording = true;
                    btn.textContent = '🛑 停止录音';
                    btn.classList.add('recording');
                    log('开始ASR录音测试');
                    
                } catch (error) {
                    log(`ASR录音失败: ${error.message}`);
                }
            } else {
                asrMediaRecorder.stop();
                isASRRecording = false;
                btn.textContent = '🎤 录音识别';
                btn.classList.remove('recording');
                log('ASR录音结束，开始识别');
            }
        }

        async function testASR(audioBlob) {
            try {
                log('开始ASR识别...');
                const formData = new FormData();
                formData.append('audio', audioBlob, 'asr-test.wav');
                formData.append('language', 'zh-CN');
                
                const response = await fetch('/api/voice/transcribe', {
                    method: 'POST',
                    body: formData
                });
                
                const text = await response.text();
                document.getElementById('asrResult').textContent = `识别结果: ${text}`;
                log(`ASR识别完成: ${text}`);
            } catch (error) {
                log(`ASR识别失败: ${error.message}`);
                document.getElementById('asrResult').textContent = '识别失败: ' + error.message;
            }
        }

        // TTS测试
        async function testTTS() {
            try {
                const text = document.getElementById('ttsText').value;
                const voice = document.getElementById('voiceSelect').value;
                
                if (!text.trim()) {
                    alert('请输入要合成的文本');
                    return;
                }
                
                log(`开始TTS合成: ${text}`);
                const url = `/api/voice/synthesize?text=${encodeURIComponent(text)}&voice=${voice}&language=zh-CN`;
                
                const response = await fetch(url);
                
                if (response.ok) {
                    const audioBlob = await response.blob();
                    const audioUrl = URL.createObjectURL(audioBlob);
                    const player = document.getElementById('ttsPlayer');
                    player.src = audioUrl;
                    player.style.display = 'block';
                    player.play();
                    log('TTS合成成功');
                } else {
                    log('TTS合成失败');
                }
            } catch (error) {
                log(`TTS合成失败: ${error.message}`);
            }
        }
    </script>
</body>
</html>